package chaincode

import (
	"encoding/json"
	"fmt"

	"github.com/hyperledger/fabric-chaincode-go/shim"
	"github.com/hyperledger/fabric-protos-go/peer"
)

type SmartContract struct{}

func (s *SmartContract) Init(stub shim.ChaincodeStubInterface) peer.Response {
	return shim.Success(nil)
}

func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
	function, args := stub.GetFunctionAndParameters()
	switch function {
	case "AddAsset":
		return s.AddAsset(stub, args)
	case "QueryAsset":
		return s.QueryAsset(stub, args)
	case "TransferAsset":
		return s.TransferAsset(stub, args)
	case "GetAllAssets":
		return s.GetAllAssets(stub)
	default:
		return shim.Error("无效的方法名")
	}
}

type Asset struct {
	ID      string `json:"id"`
	Owner   string `json:"owner"`
	Name    string `json:"name"`
	Info    string `json:"info"`
}

func (s *SmartContract) AddAsset(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 4 {
		return shim.Error("参数数量不正确，需要: ID, Owner, Name, Info")
	}

	asset := Asset{
		ID:    args[0],
		Owner: args[1],
		Name:  args[2],
		Info:  args[3],
	}

	assetJSON, err := json.Marshal(asset)
	if err != nil {
		return shim.Error(fmt.Sprintf("序列化资产失败: %s", err.Error()))
	}

	if err := stub.PutState(args[0], assetJSON); err != nil {
		return shim.Error(fmt.Sprintf("保存资产失败: %s", err.Error()))
	}

	return shim.Success(nil)
}

func (s *SmartContract) QueryAsset(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 1 {
		return shim.Error("需要提供资产ID")
	}

	assetJSON, err := stub.GetState(args[0])
	if err != nil {
		return shim.Error(fmt.Sprintf("查询资产失败: %s", err.Error()))
	}
	if assetJSON == nil {
		return shim.Error("资产不存在")
	}

	return shim.Success(assetJSON)
}

func (s *SmartContract) TransferAsset(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 2 {
		return shim.Error("需要提供资产ID和新所有者")
	}

	assetJSON, err := stub.GetState(args[0])
	if err != nil {
		return shim.Error(fmt.Sprintf("查询资产失败: %s", err.Error()))
	}
	if assetJSON == nil {
		return shim.Error("资产不存在")
	}

	var asset Asset
	if err := json.Unmarshal(assetJSON, &asset); err != nil {
		return shim.Error(fmt.Sprintf("反序列化资产失败: %s", err.Error()))
	}

	asset.Owner = args[1]
	updateJSON, err := json.Marshal(asset)
	if err != nil {
		return shim.Error(fmt.Sprintf("序列化更新后的资产失败: %s", err.Error()))
	}

	if err := stub.PutState(args[0], updateJSON); err != nil {
		return shim.Error(fmt.Sprintf("更新资产失败: %s", err.Error()))
	}

	return shim.Success(updateJSON)
}

func (s *SmartContract) GetAllAssets(stub shim.ChaincodeStubInterface) peer.Response {
	resultsIterator, err := stub.GetStateByRange("", "")
	if err != nil {
		return shim.Error(fmt.Sprintf("获取所有资产失败: %s", err.Error()))
	}
	defer resultsIterator.Close()

	var assets []Asset
	for resultsIterator.HasNext() {
		queryResponse, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(fmt.Sprintf("获取下一个资产失败: %s", err.Error()))
		}

		var asset Asset
		if err := json.Unmarshal(queryResponse.Value, &asset); err != nil {
			return shim.Error(fmt.Sprintf("反序列化资产失败: %s", err.Error()))
		}
		assets = append(assets, asset)
	}

	assetsJSON, err := json.Marshal(assets)
	if err != nil {
		return shim.Error(fmt.Sprintf("序列化资产列表失败: %s", err.Error()))
	}

	return shim.Success(assetsJSON)
}